/******************************************************************************
*
* MODULE:    uart.v
* DEVICE:     
* PROJECT:   Tarea 2 Diseño Electronico Digital
* AUTHOR:    Ricardo Dávila Castro   
* DATE:      2010 19:35:08
*
* ABSTRACT:  receptor transmisor asynccrono con protocolo RS232 Ejercicio 3
*            
*****************************************************************************/
`ifndef 	UART
`define    UART
module uart( 
input clk_50M,
input aRST,
input rxd,
output reg txd=0,
output reg [7:0] rxd_o,
output reg [7:0] parityError
);
  
  reg    [7:0]txd_alm=0;

  reg    pari=0;
  reg    [9:0]rxd_reg=0;
  reg    [4:0]count_tx=0;
  reg    bit=0;
 
  reg    [20:0]sync = 0;
  reg    clk_uart=0;
  reg    [3:0]count_rx=0;
  reg    q1;
  reg    q2;
  
  reg    trans =0;
  reg    [1:0]datos=0;  
  wire   [7:0]txd_;
  
  parameter 	waitfor 		= 'h 00,
            	startBit_rx = 'h 01,
            	r1    		= 'h 02,
            	r2    		= 'h 03,
            	r3    		= 'h 04,
            	r4    		= 'h 05,
            	r5    		= 'h 06,
            	r6    		= 'h 07,
            	r7    		= 'h 08,
            	r8    		= 'h 09,
            	parity_rx   = 'h 0A,
            	stopBit_rx  = 'h 0B,
            	startBit_tx = 'h 0C,
            	t1    		= 'h 0D,
            	t2    		= 'h 0E,
            	t3    		= 'h 0F,
            	t4    		= 'h 10,
            	t5    		= 'h 11,
            	t6    		= 'h 12,
            	t7    		= 'h 13,
            	t8    		= 'h 14,
            	parity_tx   = 'h 15,
            	stopBit_tx  = 'h 16;
  
reg [4:0]EstadoActual = waitfor;
reg [4:0]EstadoSiguiente;
                
always @ (posedge clk_50M)
 begin
   sync <= sync + 1;
   if (sync == 651)
     begin
     clk_uart <= ~clk_uart;
     sync <= 0;
   end
end

	
always @ (posedge clk_uart, posedge aRST)
	begin
		if (aRST)
			EstadoActual <= waitfor;
		else
			EstadoActual <= EstadoSiguiente;	
	end

always @	(posedge clk_uart, posedge aRST) // dos ff 
	begin
		if (aRST)
		begin
				q1 <= 0;
				q2 <= 0;
				count_rx <= 0;
				count_tx <= 0;
		end		
		else 
		begin
				if ((parityError == 8'b00000000) && (rxd_reg[9] == 1))
				begin
              			if (datos == 'b11)
              				datos <= 0;
              			else
              				datos <= datos + 1;
              			rxd_o <= rxd_reg;
              			if(rxd_o >= 'h61)
              				txd_alm <= (rxd_o - 'h20);
              			bit <= 0;  
				end	
				q1 <= rxd;
				q2 <= q1;
				if (count_rx != 'b11)
				begin
					count_rx <= count_rx + 1;
					count_tx <= count_tx + 1;
				end
				else
				begin
					count_rx <= 0;
					count_tx <= 0;
				end
		end
	 
	end
	
always @ (*)
	begin
		
		EstadoSiguiente=EstadoActual; 	
     	case(EstadoActual)
     	
     	waitfor: 
     		begin
     			if (datos == 'b11)
     			begin
     				trans = 1;				
     				EstadoSiguiente = startBit_tx;
     			end
     			if(rxd == 0)
     				EstadoSiguiente = startBit_rx;
      
     		end
            
       startBit_rx : 
       		begin
       			if((count_rx == 'b0000) && (q2 == 0))
       			begin
       				EstadoSiguiente = r1;
       			end
           end          
         
        r1: 
         	begin
         		
           		if(count_rx == 'b0011)
           		begin
           			rxd_reg[0] = q2;
           			EstadoSiguiente =r2;
           		end
         	end
           
        r2:
         	begin
         		if(count_rx == 'b0011)
         		begin
         			rxd_reg[1] = q2;
         			EstadoSiguiente = r3;            
         		end
           end
           
        r3:
          	begin
             	if(count_rx == 'b0011)
             	begin    		
             		rxd_reg[2] = q2;
             		EstadoSiguiente =r4;     
             	end
           end
           
        r4:
          	begin
             	if(count_rx == 'b0011)
             	begin
               		rxd_reg[3] = q2;
               		EstadoSiguiente =r5;     
             	end
           end
           
         r5:
          	begin
          		if(count_rx == 'b0011)
          		begin
          			rxd_reg[4] = q2;
          			EstadoSiguiente =r6;     
          		end
           end
           
         r6:
         	begin
         		if(count_rx == 'b0011)
         		begin
         			rxd_reg[5] = q2;
         			EstadoSiguiente =r7;     
         		end
           end
           
         r7:
           	begin
           		if(count_rx == 4'b0011)
           		begin
          			rxd_reg[6] = q2;
           			EstadoSiguiente =r8;     
           		end
           end
           
         r8:
           	begin
             	if(count_rx == 'b0011)
             	begin
             		rxd_reg[7] = q2;
             		EstadoSiguiente =parity_rx;     
             	end         
           end
           
         parity_rx:
         	begin
             	if(count_rx == 'b0011)
             	begin
             		rxd_reg[8] = q2;
             		EstadoSiguiente =stopBit_rx;     
             	end
           end
           
         stopBit_rx:
           	begin
             	if(count_rx == 'b0011)
             	begin
             		rxd_reg[9] = q2;
             		pari = ^rxd_reg[7:0];
             		bit = 1;
             		EstadoSiguiente = waitfor;
             	end
           end
           /*empieza la transmision*/
          startBit_tx: 
           begin
           	if (trans)
           		begin
           		    txd_alm = 0;
           			trans =0;
           			txd = 0;
           			EstadoSiguiente  = t1;
           		end
           end          
         
         t1: 
         	begin
         		
         		if(count_tx == 'b0011)
         		begin
         			txd  = txd_alm[0];
         			EstadoSiguiente  =t2;
         		end
           end
           
         t2:
         	begin
         		if(count_tx == 4'b0011)
         		begin
         			txd  = txd_alm[1];
         			EstadoSiguiente  = t3;            
         		end
           end
           
         t3:
           	begin
           		if(count_tx == 4'b0011)
           		begin
              		txd = txd_alm[2];
               		EstadoSiguiente =t4;     
           		end
           end
           
          t4:
           	begin
             	if(count_tx == 4'b0011)
             	begin
             		txd = txd_alm[3];
             		EstadoSiguiente =t5;     
             	end
           end
           
       t5:
           	begin
             	if(count_tx == 4'b0011)
             	begin
              		txd = txd_alm[4];
               		EstadoSiguiente =t6;     
             	end
           end
           
        t6:
           begin
              	if(count_tx == 4'b0011)
              	begin
              		txd =txd_alm[5];
              		EstadoSiguiente =t7;     
              	end
           end
           
         t7:
           	begin
             	if(count_tx == 4'b0011)
             	begin
               	    txd = txd_alm[6];
               		EstadoSiguiente =t8;     
             	end
           end
           
        t8:
           	begin
             	if(count_tx == 4'b0011)
             	begin
             		txd =txd_alm[7];
             		EstadoSiguiente =parity_tx;     
             	end         
           end
           
        parity_tx:
           	begin
           		if(count_tx == 4'b0011)
           			begin
           				txd = ^txd_alm;
           				EstadoSiguiente =stopBit_tx;     
           			end
           end
           
         stopBit_tx:
           begin
             	if(count_tx == 4'b0011)
             	begin
             		txd = 1;
             		EstadoSiguiente= waitfor;           
             	end
          end
         default:
           EstadoSiguiente= waitfor;
       endcase
    
       if (bit)
        begin
           if(pari != rxd_reg[8])
              parityError = 0;
            else
              parityError = 8'b11111111;
         end 
     end
    endmodule
`endif
      
      
  
  
  
  
